﻿Imports System.ComponentModel

Public Class PropertyComparer(Of T)
    Inherits System.Object
    Implements System.Collections.Generic.IComparer(Of T)

    ' Methods
    Public Sub New(ByVal [property] As PropertyDescriptor, ByVal direction As ListSortDirection)
        Me._property = [property]
        Me._direction = direction
    End Sub

    Public Function [Compare](ByVal x As T, ByVal y As T) As Integer Implements IComparer(Of T).Compare
        Dim xValue As Object = Me.GetPropertyValue(x, Me._property.Name)
        Dim yValue As Object = Me.GetPropertyValue(y, Me._property.Name)
        If (Me._direction = ListSortDirection.Ascending) Then Return Me.CompareAscending(xValue, yValue)
        Return Me.CompareDescending(xValue, yValue)
    End Function

    Private Function CompareAscending(ByVal xValue As Object, ByVal yValue As Object) As Integer
        If TypeOf xValue Is IComparable Then Return DirectCast(xValue, IComparable).CompareTo(yValue)
        If xValue Is Nothing Or yValue Is Nothing Then Return 0
        If xValue.Equals(yValue) Then Return 0
        Return xValue.ToString.CompareTo(yValue.ToString)
    End Function

    Private Function CompareDescending(ByVal xValue As Object, ByVal yValue As Object) As Integer
        Return (Me.CompareAscending(xValue, yValue) * -1)
    End Function

    Public Function Equals(ByVal xWord As T, ByVal yWord As T) As Boolean
        Return xWord.Equals(yWord)
    End Function

    Public Function GetHashCode(ByVal obj As T) As Integer
        Return obj.GetHashCode
    End Function

    Private Function GetPropertyValue(ByVal value As T, ByVal [property] As String) As Object
        Return value.GetType.GetProperty([property]).GetValue(value, Nothing)
    End Function

    ' Fields
    Private _direction As ListSortDirection
    Private _property As PropertyDescriptor

End Class
